package com.tristia.resources.impl;

import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;

import javax.annotation.Resource;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Request;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;

import org.apache.log4j.Logger;
import org.codehaus.jettison.json.JSONException;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import com.google.gdata.util.ServiceException;
import com.sun.jersey.api.NotFoundException;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.WebResource;
import com.tristia.dao.GenericDao;
import com.tristia.entity.State;
import com.tristia.entity.States;
import com.tristia.entity.User;
import com.tristia.entity.Users;

@Component
@Path("/users")
@Scope("request")
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.APPLICATION_ATOM_XML })
public class UsersResWs {
	@Resource
	GenericDao<User, Long> userDao;
	@Resource
	GenericDao<State, Long> stateDao;
	@Context 
	UriInfo ui;
	@Context
	Request request;
	private Logger log = Logger.getLogger(this.getClass());
	
	@GET
	public Users getUsers() throws UnknownHostException {
		log.info("getUsers entered");
		Users users = new Users();
		
		if (!userDao.getAll().isEmpty()){
			users.setUsers(userDao.getAll());
			Iterator<User> iter = users.getUsers().iterator();
			User user = new User();
			
			InetAddress addr = InetAddress.getLocalHost();
			String addrStr = addr.getHostAddress();
			
			while(iter.hasNext()) {
				user = iter.next();

				user.setProfileImageURL("http://"+addrStr+":9999/tristia/restws/users/"+user.getId()+"/profile_image");
//				user.setProfileImageURL("http://evilkiller.oicp.net:9999/tristia/restws/users/"+user.getId()+"/profile_image");
			}
		} else {
			throw new NotFoundException("Users not found");
		}
		
		log.info("Sending: \n\n" + users.toString() + "\n\n");
		return users;
	}
	
	@GET
	@Path("/{userId}")
	public User getUser(@PathParam("userId") long userId) throws UnknownHostException {
		log.info("getUser entered");
		User user = userDao.get(userId);	
		if (user == null) {
			throw new NotFoundException("User not found");
		} else {
			InetAddress addr = InetAddress.getLocalHost();
			String addrStr = addr.getHostAddress();
			user.setProfileImageURL("http://"+addrStr+":9999/tristia/restws/users/"+user.getId()+"/profile_image");
		}
		log.info("Sending: \n\n" + user.toString() + "\n\n");
		return user;
	}
	
	@PUT
	public Response updateUser(@QueryParam("id") String id,
			@QueryParam("username") String username,
			@QueryParam("location") String location) {
		log.info("updateUser entered");
		log.info("username: " + username);
		log.info("location : " + location);
		log.info("id : " + id);
		
		Response r;
//		URI uri =  ui.getAbsolutePath();
		if (StringUtils.hasText(id)) {
			log.info("It has an ID");
			long idd = Long.parseLong(id);
			boolean userExists = userDao.exists(idd);
			if (userExists == true) {
				log.info("We found the user with that id");
				User user = userDao.get(idd);
				user.setUsername(username);
				user.setLocation(location);
				userDao.save(user);
				log.info("Updated successfully");
//				r = Response.created(uri).build();
				r = Response.ok(user).build();
			} else {
				log.info("We do not found the user with that id");
				r = Response.noContent().build();
			}
		} else {
			log.info("It doesn't have an ID");
			log.info("Put the new user");
			User user = new User();
			user.setUsername(username);
			user.setLocation(location);
			userDao.save(user);
			log.info("Updated successfully");
			r = Response.ok(user).build();
		}
		return r;
	}
	
	@POST
	@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_ATOM_XML, MediaType.APPLICATION_XML })
	public Response addUser(@QueryParam("username") String username,
			@QueryParam("location") String location) {
		log.info("addUser entered");
		log.info("username: " + username);
		log.info("location : " + location);

		Response r;
		User user = new User();
		user.setUsername(username);
		user.setLocation(location);
		userDao.save(user);
		log.info("Updated successfully");
		r = Response.ok(user).build();
		return r;
	}
	
	@DELETE
	@Path("/{userId}")
	public void deleteUser(@PathParam("userId") String userId) {
		if(userId!=null) {
			deleteUserById(userId);
		}
		
		MultivaluedMap<String, String> queryParams = ui.getQueryParameters();
		List<String> ids = queryParams.get("userId");
		if(ids == null) {
			log.info("\n\nThe ids is null");
		} else {
			for (String currentid : ids) {
				deleteUserById(currentid);
			}
		}
	}

	private void deleteUserById(String id) {
		log.info("Delete Id: " + id);
		User user = userDao.get(Long.parseLong(id));
		if (user == null) {
			log.info("Null was returned for ID: " + id);
		} else {
			userDao.remove(Long.parseLong(id));
			log.info("Deleted the CD with ID:" + id);
		}
	}
	
	@GET
	@Path("/{userId}/profile_image")
	public Response getProfileImage(@PathParam("userId") long userId) throws IOException {
		log.info("getProfileImage entered");
		User user = getUser(userId);
/*		File file = new File("D://images41_normal.jpg");
		FileInputStream fin = new FileInputStream(file);
		byte fileContent[] = new byte[(int)file.length()];
		fin.read(fileContent);*/
		byte[] image = user.getImage();
		if (image == null) throw new NotFoundException("User profile image not found");
		return Response.ok(image).build();
	}
	
	@GET
	@Path("/{userId}/states")
	public States getStatesByUserID(@PathParam("userId") long userId) throws IOException, ServiceException, JSONException {
		log.info("getStatesByUserID entered");
		States states = new States();
		
		HashMap<String, Object> queryParams = new HashMap<String, Object>();
        queryParams.put("progress", "NONE");
        queryParams.put("user_id", userId);
        List<State> statesList = stateDao.findByNamedQuery("State.findValidStateByUserID", queryParams);
        log.info("States num: " + statesList.size());
        
		if (!statesList.isEmpty()) {
			states.getStates().addAll(statesList);
			Iterator<State> iter = states.getStates().iterator();
			State state = new State();
			while(iter.hasNext()) {
				state = iter.next();
				state.setUsername(userDao.get(state.getUser_id()).getUsername());
			}
		} else {
			log.info("States with the User ID not found from Tristia Database");
		}
        
/*		User user = new User();
		user = userDao.get(userId);

		log.info("States num: " + user.getStates().size());
		if (!user.getStates().isEmpty()) {
			states.getStates().addAll(user.getStates());
			Iterator<State> iter = states.getStates().iterator();
			State state = new State();
			while(iter.hasNext()) {
				state = iter.next();
				state.setUsername(userDao.get(state.getUser_id()).getUsername());
			}
		} else {
			log.info("States with the User ID not found from Tristia Database");
		}*/

		log.info("Sending: \n\n" + states.toString() + "\n\n");
		return states;
	}
	
	@GET
	@Path("/{userId}/states/{stateId}")
	public State getState(@PathParam("stateId") long stateId) {
		log.info("getState entered");
		State state = stateDao.get(stateId);
		if (state == null)throw new NotFoundException("State not found");
		log.info("Sending: \n\n" + state.toString() + "\n\n");
		return state;
	}
	
	@GET
	@Path("/{userId}/matching_users")
	public Response getMatchingUsers(@PathParam("userId") long userId) throws IOException {
		log.info("getState entered");
		User user = userDao.get(userId);
		if (user == null)throw new NotFoundException("User not found");
		log.info("Sending: \n\n" + user.toString() + "\n\n");
		
		Client client = Client.create();
		WebResource webResource = client.resource("http://127.0.0.1:8080/sign");
		String tmp = webResource.entity(user, MediaType.APPLICATION_JSON).post(String.class);
		log.info("Response: "+tmp);
		
		return Response.ok(tmp).build();
	}
	
	@GET
	@Path("/save_tags")
	public Response saveTags() throws IOException {
		log.info("getState entered");
		List<User> usersList = userDao.getAll();
		if (usersList == null)throw new NotFoundException("User not found");
		Users users = new Users();
		users.setUsers(usersList);
		log.info("Sending: \n\n" + users.toString() + "\n\n");
		
		Client client = Client.create();
		//WebResource webResource = client.resource("http://innocencelight.appspot.com/save_tags");
		WebResource webResource = client.resource("http://127.0.0.1:8080/save_tags");
		String tmp = webResource.entity(users, MediaType.APPLICATION_JSON).post(String.class);
		log.info("Response: "+tmp);
		
		return Response.ok(tmp).build();
	}

}
